package com.crazy.web.config.shiro;

import com.crazy.model.major.dto.UserSession;
import com.crazy.model.major.entity.TUser;
import com.crazy.web.service.user.PermissionService;
import com.crazy.web.service.user.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Set;

/**
 * 用于登录和权限的验证
 *
 * @Author: zhaochaofeng
 * @Date: 2020-11-17
 * @Description:
 */
@Slf4j
@Component
public class AccountRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;
    @Autowired
    private PermissionService permissionService;
    /**
     * 第一步 账号认证
     *
     * @return
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //编写shiro判断逻辑，判断用户名和密码
        //1.判断用户名  token中的用户信息是登录时候传进来的
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        //让cookie生效，关闭浏览器后再次打开可以自动登录（前提：cookie未失效）
        upToken.setRememberMe(true);
        String username = upToken.getUsername();
        String password = new String(upToken.getPassword());
        if (StringUtils.isEmpty(username)) {
            throw new AccountException("用户名不能为空");
        }
        if (StringUtils.isEmpty(password)) {
            throw new AccountException("密码不能为空");
        }
        TUser tUser = userService.getByUserName(username);
        if (tUser==null) {
            throw new AccountException("当前用户不存在");
        }
        UserSession userSession = userService.getUserSession(tUser.getId());
        userSession.setMenus(permissionService.getMenus(userSession.getId()));
        if(userSession.getLocked().equals(1)){
            throw new AccountException("账号被锁定，请联系管理员");
        }
        // 2.此处第一个参数请看源码注释 对应着下面权限验证的传参
        return new SimpleAuthenticationInfo(userSession, tUser.getPassword(), ByteSource.Util.bytes(tUser.getId().toString()), getName());
    }

    /**
     * 第二步 权限验证
     *
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        if (principals == null) {
            throw new AuthorizationException("PrincipalCollection method argument cannot be null.");
        }
        UserSession userSession = (UserSession) getAvailablePrincipal(principals);
        //获取当前账号所拥有的角色名称
        Set<String> requireRoles = permissionService.getUserRoleNames(userSession.getId());
        //获取当前账号所拥有的菜单
        Set<String> requireLimits = permissionService.getLimit(userSession.getId());
        //给资源进行授权
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setRoles(requireRoles);
        info.setStringPermissions(requireLimits);
        return info;
    }
}
